import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createReactAgent } from "langchain/agents";
import { pull } from "langchain/hub";
import { DynamicTool } from "@langchain/core/tools";
import { searchPorts, pathPlanning } from "./network";

// 1. Define tools based on the map controller
const createGisTools = (mapTools, context) => {
  const drawPointTool = new DynamicTool({
    name: "drawPointOnMap",
    description: "在地图上绘制单个点（标记）。用于标记特定位置。输入应为包含'lat'、'lng'和可选的'popupText'的JSON对象。",
    func: async (input) => {
      try {
        const { lat, lng, popupText } = JSON.parse(input);
        if (lat === undefined || lng === undefined) {
          return "Error: Missing required parameters 'lat' and 'lng'.";
        }
        return mapTools.drawPoint({ lat, lng, popupText });
      } catch (e) {
        return `Error processing input for drawPointOnMap: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const drawPolylineTool = new DynamicTool({
    name: "drawPolylineOnMap",
    description: "在地图上绘制连接一系列点的线。用于路线、路径或边界。输入应为包含'coordinates'（{lat, lng}对象数组）和可选的'color'和'popupText'的JSON对象。",
    func: async (input) => {
      try {
        const { coordinates, color, popupText } = JSON.parse(input);
        if (!coordinates || !Array.isArray(coordinates) || coordinates.length < 2) {
          return "Error: 'coordinates' must be an array of at least two {lat, lng} objects.";
        }
        return mapTools.drawPolyline({ coordinates, color, popupText });
      } catch (e) {
        return `Error processing input for drawPolylineOnMap: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const drawPolygonTool = new DynamicTool({
    name: "drawPolygonOnMap",
    description: "在地图上绘制闭合形状（多边形）。用于区域、地区或区域。输入应为包含'coordinates'（{lat, lng}对象数组）和可选的'color'、'opacity'和'popupText'的JSON对象。",
    func: async (input) => {
      try {
        const { coordinates, color, opacity, popupText } = JSON.parse(input);
        if (!coordinates || !Array.isArray(coordinates) || coordinates.length < 3) {
          return "Error: 'coordinates' must be an array of at least three {lat, lng} objects.";
        }
        return mapTools.drawPolygon({ coordinates, color, opacity, popupText });
      } catch (e) {
        return `Error processing input for drawPolygonOnMap: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const clearMapTool = new DynamicTool({
    name: "clearMap",
    description: "清除地图上的所有绘制内容（点、线、多边形）。用于重新开始。无需输入。",
    func: async () => {
      return mapTools.clearMap();
    },
  });

  const setMapViewTool = new DynamicTool({
    name: "setMapView",
    description: "将地图视图中心设置为特定的经纬度并调整缩放级别。用于聚焦特定区域。输入应为包含'center'（[lat, lng]数组）和可选的'zoom'的JSON对象。",
    func: async (input) => {
      try {
        const { center, zoom } = JSON.parse(input);
        if (!center || !Array.isArray(center) || center.length !== 2) {
          return "Error: 'center' must be an array of [latitude, longitude].";
        }
        return mapTools.setMapView(center, zoom);
      } catch (e) {
        return `Error processing input for setMapView: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const searchPortTool = new DynamicTool({
    name: "searchPort",
    description: "根据港口名称模糊查询港口信息。涉及到港口位置就使用该工具查询。输入应为包含'name'的JSON对象。",
    func: async (input) => {
      try {
        const { name } = JSON.parse(input);
        if (!name) {
          return "Error: Missing required parameter 'name'.";
        }
        const response = await searchPorts({ name });
        return JSON.stringify(response.data);
      } catch (e) {
        return `Error processing input for searchPort: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  // 新增：并行查询多个港口并规划路径的工具
  const searchPortsAndPlanPathTool = new DynamicTool({
    name: "searchPortsAndPlanPath",
    description: "并行查询多个港口信息并规划它们之间的路径。输入应为包含'ports'（港口名称数组）和可选的'startText'、'endText'的JSON对象。例如：{\"ports\": [\"青岛港\", \"烟台港\"]}。此工具会同时查询所有港口，然后规划第一个港口到最后一个港口的路径，并在地图上绘制。",
    func: async (input) => {
      try {
        const { ports, startText = '起点', endText = '终点' } = JSON.parse(input);
        if (!ports || !Array.isArray(ports) || ports.length < 2) {
          return "Error: 'ports' must be an array of at least two port names.";
        }

        // 并行查询所有港口
        const portQueries = ports.map(async (portName) => {
          try {
            const response = await searchPorts({ name: portName });
            return {
              name: portName,
              data: response.data,
              success: true
            };
          } catch (error) {
            return {
              name: portName,
              error: error.message,
              success: false
            };
          }
        });

        const portResults = await Promise.all(portQueries);
        
        // 检查是否有查询失败的港口
        const failedPorts = portResults.filter(result => !result.success);
        if (failedPorts.length > 0) {
          return `Error: Failed to query ports: ${failedPorts.map(p => p.name).join(', ')}`;
        }

        // 获取第一个和最后一个港口的位置
        const firstPort = portResults[0];
        const lastPort = portResults[portResults.length - 1];

        // 从港口数据中提取经纬度（假设数据结构包含经纬度信息）
        const getPortCoordinates = (portData) => {
          // 这里需要根据实际的港口数据结构来提取经纬度
          // 假设港口数据中有经纬度字段
          if (portData && portData.length > 0) {
            const port = portData[0]; // 取第一个匹配的港口
            
            // 尝试多种可能的经纬度字段名
            const possibleLatFields = ['latitude', 'lat', 'y', 'Y'];
            const possibleLngFields = ['longitude', 'lng', 'lon', 'x', 'X'];
            
            let lat = null;
            let lng = null;
            
            // 查找纬度
            for (const field of possibleLatFields) {
              if (port[field] !== undefined && port[field] !== null) {
                lat = parseFloat(port[field]);
                break;
              }
            }
            
            // 查找经度
            for (const field of possibleLngFields) {
              if (port[field] !== undefined && port[field] !== null) {
                lng = parseFloat(port[field]);
                break;
              }
            }
            
            if (lat !== null && lng !== null && !isNaN(lat) && !isNaN(lng)) {
              return { lat, lng };
            }
          }
          
          // 如果无法提取经纬度，返回错误信息
          console.error('港口数据结构:', JSON.stringify(portData, null, 2));
          throw new Error(`无法从港口数据中提取经纬度。请检查数据结构: ${JSON.stringify(portData)}`);
        };

        const startCoords = getPortCoordinates(firstPort.data);
        const endCoords = getPortCoordinates(lastPort.data);

        // 规划路径
        const pathResponse = await pathPlanning({
          start: [startCoords.lat, startCoords.lng],
          end: [endCoords.lat, endCoords.lng]
        });

        // 存储规划的路径
        context.plannedPath = {
          path: pathResponse.data,
          start: startCoords,
          end: endCoords
        };

        // 绘制路径和标记
        if (pathResponse.data && pathResponse.data.data && pathResponse.data.data.lines) {
          const coordinates = pathResponse.data.data.lines.map(point => {
            const [lat, lng] = point.split(',');
            return { lat: parseFloat(lat), lng: parseFloat(lng) };
          });

          // 绘制路径线
          await mapTools.drawPolyline({
            coordinates,
            color: 'blue',
            popupText: `${firstPort.name}到${lastPort.name}的路径`
          });

          // 标记起点
          await mapTools.drawPoint({
            lat: startCoords.lat,
            lng: startCoords.lng,
            popupText: `${startText}: ${firstPort.name}`
          });

          // 标记终点
          await mapTools.drawPoint({
            lat: endCoords.lat,
            lng: endCoords.lng,
            popupText: `${endText}: ${lastPort.name}`
          });

          // 如果有中间港口，也标记出来
          if (ports.length > 2) {
            for (let i = 1; i < portResults.length - 1; i++) {
              const middlePort = portResults[i];
              const coords = getPortCoordinates(middlePort.data);
              await mapTools.drawPoint({
                lat: coords.lat,
                lng: coords.lng,
                popupText: `途经: ${middlePort.name}`
              });
            }
          }

          const pathLength = coordinates.length;
          return `成功并行查询了${ports.length}个港口，并规划了从${firstPort.name}到${lastPort.name}的路径（包含${pathLength}个点）。路径已在地图上绘制。`;
        } else {
          return "路径规划成功，但路径数据格式异常。";
        }

      } catch (e) {
        return `Error processing input for searchPortsAndPlanPath: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const getCurrentLocationTool = new DynamicTool({
    name: "getCurrentLocation",
    description: "获取用户当前位置。无需输入。",
    func: async () => {
      try {
        return new Promise((resolve, reject) => {
          if (!navigator.geolocation) {
            reject("Geolocation is not supported by your browser");
          }
          navigator.geolocation.getCurrentPosition(
            (position) => {
              resolve(JSON.stringify({
                lat: position.coords.latitude,
                lng: position.coords.longitude
              }));
            },
            (error) => {
              reject(`Error getting location: ${error.message}`);
            }
          );
        });
      } catch (e) {
        return `Error getting current location: ${e.message}`;
      }
    },
  });

  const planPathTool = new DynamicTool({
    name: "planPath",
    description: "规划两点之间的路径。输入应为包含'start'和'end'（{lat, lng}对象）的JSON对象。此工具的输出是一个摘要，实际路径数据被存储并在内部供`drawPathWithMarkers`使用。",
    func: async (input) => {
      try {
        const { start, end } = JSON.parse(input);
        if (!start || !end) {
          return "Error: Missing required parameters 'start' and 'end'.";
        }

        const response = await pathPlanning(
          {
            start: [start.lat, start.lng],
            end: [end.lat, end.lng]
          }
        );

        context.plannedPath = {
          path: response.data,
          start: start,
          end: end
        };
        
        const pathLength = response.data?.length || 0;
        return `成功规划了包含 ${pathLength} 个点的路径。现在可以使用 drawPathWithMarkers 绘制它。`;
      } catch (e) {
        return `Error processing input for planPath: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  const drawPathWithMarkersTool = new DynamicTool({
    name: "drawPathWithMarkers",
    description: "在地图上绘制先前规划的路径，并标记起点和终点。此工具使用由`planPath`规划的最新路径。输入可以是空的，也可以是包含'start'和'end'文本标签的JSON对象。",
    func: async (input) => {
      try {
        if (!context.plannedPath) {
          return "错误：尚未规划路径。请先使用planPath。";
        }
        
        const { path, start, end } = context.plannedPath;
        
        let { startText, endText } = { startText: '起点', endText: '终点' };
        if (input) {
            try {
                const parsedInput = JSON.parse(input);
                startText = parsedInput.startText || startText;
                endText = parsedInput.endText || endText;
            } catch (e) {
                // Ignore if input is not valid JSON, use defaults
            }
        }

        if (!path || !start || !end) {
          return "Error: Missing path data from planned path.";
        }
        // 绘制路径
        const coordinates = path.data.lines.map(point=>{
          const [lat, lng] = point.split(',');
          return { lat: parseFloat(lat), lng: parseFloat(lng) };
        });
        
        await mapTools.drawPolyline({
          coordinates,
          color: 'blue',
          popupText: '规划路径'
        });


        // 标记起点
        await mapTools.drawPoint({
          lat: start.lat,
          lng: start.lng,
          popupText: startText
        });

        // 标记终点
        await mapTools.drawPoint({
          lat: end.lat,
          lng: end.lng,
          popupText: endText
        });

        return "已成功绘制路径并标记起点和终点。";
      } catch (e) {
        return `Error processing input for drawPathWithMarkers: ${e.message}. Input should be a valid JSON.`;
      }
    },
  });

  return [
    drawPointTool,
    drawPolylineTool,
    drawPolygonTool,
    clearMapTool,
    setMapViewTool,
    searchPortTool,
    searchPortsAndPlanPathTool, // 新增的并行处理工具
    getCurrentLocationTool,
    planPathTool,
    drawPathWithMarkersTool
  ];
};
//历史记录
export const chatHistory = [];

// 专题图聊天历史记录
export const thematicChatHistory = [];

// 专题图工具创建函数
const createThematicTools = (thematicTools, context) => {
  // 使用大模型理解自然语言并构建图层配置对象的辅助函数
  const parseLayerConfig = async (input, layerType) => {
    const text = typeof input === "string" ? input : JSON.stringify(input);
    
    // 默认配置
    let defaultConfig = {
      particle: false,
      speed: false,
      arrow: false,
      feather: false,
      scalar: false,
      label: false
    };
    
    // 检查是否指定了具体的图层类型
    const hasSpecificLayerType = text && (
      /粒子|particle/i.test(text) ||
      /速度|speed/i.test(text) ||
      /箭头|arrow/i.test(text) ||
      /风羽|feather/i.test(text) ||
      /标量|scalar/i.test(text) ||
      /标签|label/i.test(text)
    );
    
    // 根据图层类型和是否指定了具体类型设置默认值
    if (!hasSpecificLayerType) {
      // 如果没有指定具体类型，则同时加载标量场和速度场
      defaultConfig.scalar = true;
      defaultConfig.speed = true;
    } else {
      // 如果指定了具体类型，则使用原来的默认逻辑
      if (layerType === 'wind') {
        defaultConfig.speed = true;
      } else if (layerType === 'current') {
        defaultConfig.speed = true;
      } else if (layerType === 'seatemp') {
        defaultConfig.scalar = true;
      }
    }

    // 如果输入为空或者很简单，直接返回默认配置
    if (!text || text.trim().length < 3) {
      return defaultConfig;
    }

    try {
      // 配置LLM
      const llm = new ChatOpenAI({
        modelName: 'gpt-4o-mini',
        temperature: 0,
        openAIApiKey: 'sk-1UFn4uObTYmMq2J38sSnSgwQT6sQOmCcIVmkL8fUCR8X0BLA',
        configuration: {
          baseURL: 'https://ai.nengyongai.cn/v1',
        }
      });

      // 构建提示词
      const prompt = `你是一个地理信息系统专家，需要根据用户的自然语言描述，理解用户想要的图层配置。

【图层类型】: ${layerType}
【用户描述】: ${text}

【可用配置选项】:
- particle: 粒子流动画效果（动态粒子、粒子流、流动效果、动画粒子等）
- speed: 速度场显示（速度场、速度分布、速度等值线等）
- arrow: 箭头显示（箭头、方向箭头、矢量箭头等）
- feather: 风羽显示（风羽、羽毛状、风向标等）
- scalar: 标量场显示（温度场、标量场、等值面、颜色场等，主要用于海温）
- label: 标签显示（标签、文字标注、数值标注、数值等）

【图层类型说明】:
- wind（风场）: 通常支持 particle、speed、arrow、feather、label
- current（洋流）: 通常支持 particle、speed、arrow、feather、label  
- seatemp（海温）: 通常支持 scalar、label

【默认配置】:
${JSON.stringify(defaultConfig, null, 2)}

请根据用户的描述，判断用户想要启用哪些配置选项。如果用户没有明确指定，请使用默认配置。

重要：你必须返回一个合法的JSON对象，格式如下：
{
  "particle": true/false,
  "speed": true/false,
  "arrow": true/false,
  "feather": true/false,
  "scalar": true/false,
  "label": true/false
}

请只返回JSON对象，不要包含其他文字。`;

      const response = await llm.invoke(prompt);
      const result = response.content.trim(); // 返回的JSON字符串
      
      // 尝试解析LLM返回的JSON
      let config;
      try {
        // 提取JSON部分（处理可能的markdown格式）
        const jsonMatch = result.match(/\{[\s\S]*\}/);
        if (jsonMatch) {
          config = JSON.parse(jsonMatch[0]);
        } else {
          config = JSON.parse(result);
        }
        
        // 验证配置对象是否包含所有必需的字段
        const requiredFields = ['particle', 'speed', 'arrow', 'feather', 'scalar', 'label'];
        for (const field of requiredFields) {
          if (!(field in config)) {
            config[field] = defaultConfig[field];
          }
        }
        
        // console.log('AI解析的图层配置:', config);
        return config;
        
      } catch (parseError) {
        console.warn('LLM返回的JSON解析失败，使用默认配置:', parseError, 'Response:', result);
        return defaultConfig;
      }
      
    } catch (error) {
      console.warn('调用LLM解析图层配置失败，使用默认配置:', error);
      return defaultConfig;
    }
  };

  // 从自然语言中解析日期和时间的辅助函数
  const parseDateTimeFromText = (text) => {
    if (!text) {
      // 如果没有文本，返回当前日期和默认时间
      const now = new Date();
      const date = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
      return { date, time: "12" };
    }

    const textLower = text.toLowerCase();
    
    // 默认值
    const now = new Date();
    let date = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
    let time = "12";
    
    // 解析日期模式
    // 格式：YYYY-MM-DD, YYYY/MM/DD, MM-DD, MM/DD
    const datePatterns = [
      /(\d{4})[年\/\-](\d{1,2})[月\/\-](\d{1,2})[日]?/,  // 2024年6月1日, 2024-06-01, 2024/06/01
      /(\d{1,2})[月\/\-](\d{1,2})[日]?/,                // 6月1日, 06-01, 06/01
      /(\d{4})(\d{2})(\d{2})/,                         // 20240601
    ];
    
    for (const pattern of datePatterns) {
      const match = textLower.match(pattern);
      if (match) {
        if (match.length === 4) {
          // 完整日期格式
          const year = match[1];
          const month = String(match[2]).padStart(2, '0');
          const day = String(match[3]).padStart(2, '0');
          date = `${year}-${month}-${day}`;
        } else if (match.length === 3) {
          // 只有月日格式
          const month = String(match[1]).padStart(2, '0');
          const day = String(match[2]).padStart(2, '0');
          date = `${now.getFullYear()}-${month}-${day}`;
        }
        break;
      }
    }
    
    // 解析相对日期
    if (/今天|今日/.test(textLower)) {
      // 今天，使用当前日期
      date = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
    } else if (/昨天|昨日/.test(textLower)) {
      // 昨天
      const yesterday = new Date(now);
      yesterday.setDate(yesterday.getDate() - 1);
      date = `${yesterday.getFullYear()}-${String(yesterday.getMonth()+1).padStart(2,'0')}-${String(yesterday.getDate()).padStart(2,'0')}`;
    } else if (/明天|明日/.test(textLower)) {
      // 明天
      const tomorrow = new Date(now);
      tomorrow.setDate(tomorrow.getDate() + 1);
      date = `${tomorrow.getFullYear()}-${String(tomorrow.getMonth()+1).padStart(2,'0')}-${String(tomorrow.getDate()).padStart(2,'0')}`;
    }
    
    // 解析时间（小时）
    const timePatterns = [
      /(\d{1,2})[时点：:](\d{1,2})?/,  // 12时, 12点, 12:00
      /(\d{1,2})时/,                   // 12时
      /(\d{1,2})点/,                   // 12点
    ];
    
    for (const pattern of timePatterns) {
      const match = textLower.match(pattern);
      if (match) {
        time = String(match[1]).padStart(2, '0');
        break;
      }
    }
    
    // 特殊时间描述
    if (/上午|早上|早晨/.test(textLower)) {
      time = "08";
    } else if (/中午|正午/.test(textLower)) {
      time = "12";
    } else if (/下午/.test(textLower)) {
      time = "15";
    } else if (/晚上|夜间/.test(textLower)) {
      time = "20";
    }
    
    return { date, time };
  };

  // 加载风场
  const loadAllWindTool = new DynamicTool({
    name: "loadAllWind",
    description: "加载风场图层。支持粒子流、速度场、箭头、风羽、标签。可以从自然语言中解析日期时间。输入应为包含可选'date'、'time'和'description'的JSON对象。例如：{\"description\":\"加载2024年6月1日12时的粒子流风场\"}或{\"date\":\"2024-06-01\",\"time\":\"12\",\"description\":\"加载粒子流和箭头风场\"}。如果没有指定日期，默认使用当前日期；如果没有指定类型，默认加载速度场。",
    func: async (input) => {
      try {
        const params = JSON.parse(input);
        
        let { date, time, description = '' } = params;
        
        // 如果没有直接指定日期时间，尝试从描述中解析
        if (!date || !time) {
          const parsedDateTime = parseDateTimeFromText(description);
          date = date || parsedDateTime.date;
          time = time || parsedDateTime.time;
        }
        
        // 解析图层配置
        const config = await parseLayerConfig(description, 'wind');
        console.log(config);
        
        return thematicTools.loadAllWind(date, time, config);
      } catch (e) {
        return `加载风场时出错: ${e.message}`;
      }
    },
  });

  // 清除风场
  const removeWindTool = new DynamicTool({
    name: "removeWind",
    description: "清除风场图层。可以清除所有类型或指定类型。输入可以为空（清除所有）或包含描述的JSON对象，例如：{\"description\":\"清除粒子风场\"}。",
    func: async (input) => {
      try {
        if (!input) {
          return thematicTools.removeWind();
        }
        
        const params = JSON.parse(input);
        const { description = '' } = params;
        
        if (!description) {
          return thematicTools.removeWind();
        }
        
        // 解析要清除的类型
        const config = await parseLayerConfig(description, 'wind');
        return thematicTools.removeWind(config);
      } catch (e) {
        return `清除风场时出错: ${e.message}`;
      }
    },
  });

  // 加载洋流
  const loadAllCurrentTool = new DynamicTool({
    name: "loadAllCurrent",
    description: "加载洋流图层。支持粒子流、速度场、箭头、风羽、标签。可以从自然语言中解析日期时间。输入应为包含可选'date'、'time'和'description'的JSON对象。例如：{\"description\":\"加载2024年6月1日15时的箭头洋流\"}或{\"date\":\"2024-06-01\",\"time\":\"12\",\"description\":\"加载箭头洋流\"}。如果没有指定日期，默认使用当前日期；如果没有指定类型，默认加载速度场。",
    func: async (input) => {
      try {
        const params = JSON.parse(input);
        let { date, time, description = '' } = params;
        
        // 如果没有直接指定日期时间，尝试从描述中解析
        if (!date || !time) {
          const parsedDateTime = parseDateTimeFromText(description);
          date = date || parsedDateTime.date;
          time = time || parsedDateTime.time;
        }
        
        // 解析图层配置
        const config = await parseLayerConfig(description, 'current');
        
        return thematicTools.loadAllCurrent(date, time, config);
      } catch (e) {
        return `加载洋流时出错: ${e.message}`;
      }
    },
  });

  // 清除洋流
  const removeCurTool = new DynamicTool({
    name: "removeCur",
    description: "清除洋流图层。可以清除所有类型或指定类型。输入可以为空（清除所有）或包含描述的JSON对象，例如：{\"description\":\"清除箭头洋流\"}。",
    func: async (input) => {
      try {
        if (!input) {
          return thematicTools.removeCur();
        }
        
        const params = JSON.parse(input);
        const { description = '' } = params;
        
        if (!description) {
          return thematicTools.removeCur();
        }
        
        // 解析要清除的类型
        const config = await parseLayerConfig(description, 'current');
        return thematicTools.removeCur(config);
      } catch (e) {
        return `清除洋流时出错: ${e.message}`;
      }
    },
  });

  // 加载海温
  const loadAllSeatempTool = new DynamicTool({
    name: "loadAllSeatemp",
    description: "加载海温图层。支持标量场、标签。可以从自然语言中解析日期时间。输入应为包含可选'date'、'time'和'description'的JSON对象。例如：{\"description\":\"加载昨天上午的标量场海温\"}或{\"date\":\"2024-06-01\",\"time\":\"12\",\"description\":\"加载标量场海温\"}。如果没有指定日期，默认使用当前日期；如果没有指定类型，默认加载标量场。",
    func: async (input) => {
      try {
        const params = JSON.parse(input);
        let { date, time, description = '' } = params;
        
        // 如果没有直接指定日期时间，尝试从描述中解析
        if (!date || !time) {
          const parsedDateTime = parseDateTimeFromText(description);
          date = date || parsedDateTime.date;
          time = time || parsedDateTime.time;
        }
        
        // 解析图层配置
        const config = await parseLayerConfig(description, 'seatemp');
        
        return thematicTools.loadAllSeatemp(date, time, config);
      } catch (e) {
        return `加载海温时出错: ${e.message}`;
      }
    },
  });

  // 清除海温
  const removeSeatempTool = new DynamicTool({
    name: "removeSeatemp",
    description: "清除海温图层。可以清除所有类型或指定类型。输入可以为空（清除所有）或包含描述的JSON对象，例如：{\"description\":\"清除标量场海温\"}。",
    func: async (input) => {
      try {
        if (!input) {
          return thematicTools.removeSeatemp();
        }
        
        const params = JSON.parse(input);
        const { description = '' } = params;
        
        if (!description) {
          return thematicTools.removeSeatemp();
        }
        
        // 解析要清除的类型
        const config = await parseLayerConfig(description, 'seatemp');
        return thematicTools.removeSeatemp(config);
      } catch (e) {
        return `清除海温时出错: ${e.message}`;
      }
    },
  });

  // 智能自然语言控制图层
  const smartThematicControlTool = new DynamicTool({
    name: "smartThematicControl",
    description: "根据用户的自然语言输入智能加载或清除风场、洋流、海温图层。支持从自然语言中解析日期时间。例如：'加载粒子风场'、'显示箭头洋流'、'加载标量场海温'、'清除所有图层'、'加载2024年6月1日的风场'、'显示昨天下午的洋流'。支持混合操作，如'加载风场和海温'。",
    func: async (input) => {
      try {
        const text = (typeof input === "string" ? input : JSON.stringify(input)).toLowerCase();
        
        // 从自然语言中解析日期时间
        const parsedDateTime = parseDateTimeFromText(text);
        const date = parsedDateTime.date;
        const time = parsedDateTime.time;

        let result = [];

        // 清除全部
        if (/清除.*(全部|所有)/.test(text) || /移除.*(全部|所有)/.test(text)) {
          result.push(await thematicTools.removeWind());
          result.push(await thematicTools.removeCur());
          result.push(await thematicTools.removeSeatemp());
          return result.join('\n');
        }

        // 处理风场
        if (/风场/.test(text)) {
          if (/加载|显示|开启/.test(text)) {
            const config = await parseLayerConfig(text, 'wind');
            result.push(await thematicTools.loadAllWind(date, time, config));
          } else if (/清除|移除|关闭/.test(text)) {
            if (/粒子|速度|箭头|风羽|标签/.test(text)) {
              const config = await parseLayerConfig(text, 'wind');
              result.push(await thematicTools.removeWind(config));
            } else {
              result.push(await thematicTools.removeWind());
            }
          }
        }

        // 处理洋流
        if (/洋流/.test(text)) {
          if (/加载|显示|开启/.test(text)) {
            const config = await parseLayerConfig(text, 'current');
            result.push(await thematicTools.loadAllCurrent(date, time, config));
          } else if (/清除|移除|关闭/.test(text)) {
            if (/粒子|速度|箭头|风羽|标签/.test(text)) {
              const config = await parseLayerConfig(text, 'current');
              result.push(await thematicTools.removeCur(config));
            } else {
              result.push(await thematicTools.removeCur());
            }
          }
        }

        // 处理海温
        if (/海温/.test(text)) {
          if (/加载|显示|开启/.test(text)) {
            const config = await parseLayerConfig(text, 'seatemp');
            result.push(await thematicTools.loadAllSeatemp(date, time, config));
          } else if (/清除|移除|关闭/.test(text)) {
            if (/标量|标签/.test(text)) {
              const config = await parseLayerConfig(text, 'seatemp');
              result.push(await thematicTools.removeSeatemp(config));
            } else {
              result.push(await thematicTools.removeSeatemp());
            }
          }
        }

        // 组合操作处理
        if ((/风场.*(和|与).*海温/.test(text) || /海温.*(和|与).*风场/.test(text)) && /加载|显示/.test(text)) {
          const windConfig = await parseLayerConfig(text, 'wind');
          const seatempConfig = await parseLayerConfig(text, 'seatemp');
          result.push(await thematicTools.loadAllWind(date, time, windConfig));
          result.push(await thematicTools.loadAllSeatemp(date, time, seatempConfig));
        }

        if ((/风场.*(和|与).*洋流/.test(text) || /洋流.*(和|与).*风场/.test(text)) && /加载|显示/.test(text)) {
          const windConfig = await parseLayerConfig(text, 'wind');
          const currentConfig = await parseLayerConfig(text, 'current');
          result.push(await thematicTools.loadAllWind(date, time, windConfig));
          result.push(await thematicTools.loadAllCurrent(date, time, currentConfig));
        }

        if ((/洋流.*(和|与).*海温/.test(text) || /海温.*(和|与).*洋流/.test(text)) && /加载|显示/.test(text)) {
          const currentConfig = await parseLayerConfig(text, 'current');
          const seatempConfig = await parseLayerConfig(text, 'seatemp');
          result.push(await thematicTools.loadAllCurrent(date, time, currentConfig));
          result.push(await thematicTools.loadAllSeatemp(date, time, seatempConfig));
        }

        // 加载全部
        if ((/全部|所有/.test(text)) && (/加载|显示/.test(text))) {
          const windConfig = await parseLayerConfig(text, 'wind');
          const currentConfig = await parseLayerConfig(text, 'current');
          const seatempConfig = await parseLayerConfig(text, 'seatemp');
          result.push(await thematicTools.loadAllWind(date, time, windConfig));
          result.push(await thematicTools.loadAllCurrent(date, time, currentConfig));
          result.push(await thematicTools.loadAllSeatemp(date, time, seatempConfig));
        }

        if (result.length === 0) {
          return "未识别到有效的图层操作指令。请尝试使用'加载风场'、'显示洋流'、'清除海温'等表达方式。";
        }
        
        return result.join('\n');
      } catch (e) {
        return `智能控制图层时出错: ${e.message}`;
      }
    },
  });

  return [
    loadAllWindTool,
    removeWindTool,
    loadAllCurrentTool,
    removeCurTool,
    loadAllSeatempTool,
    removeSeatempTool,
    smartThematicControlTool
  ];
};

// 专题图智能体运行函数
export const runThematicAgent = async (input, onIntermediateStep, thematicTools, config = {}) => {
  const agentContext = {};
  const tools = createThematicTools(thematicTools, agentContext);

  try {
    const prompt = await pull("hwchase17/react-chat");

    // const defaultConfig = {
    //   baseURL: 'https://api.siliconflow.cn',
    //   openAIApiKey: 'sk-kxvlqqwjbkgizqedqrcrgnaxpzuluyyjbbplygzomtsmmdmc',
    //   modelName: 'Pro/deepseek-ai/DeepSeek-V3',
    //   temperature: 0,
    //   maxTokens: null
    // };

    const defaultConfig = {
      baseURL: 'https://ai.nengyongai.cn/v1',
      openAIApiKey: 'sk-1UFn4uObTYmMq2J38sSnSgwQT6sQOmCcIVmkL8fUCR8X0BLA',
      modelName: 'gpt-4o-mini',
      temperature: 0,
      maxTokens: null
    };

    const finalConfig = { ...defaultConfig, ...config };

    const llmConfig = {
      modelName: finalConfig.modelName,
      temperature: finalConfig.temperature,
      openAIApiKey: finalConfig.openAIApiKey,
      configuration: {
        baseURL: finalConfig.baseURL,
      }
    };

    if (finalConfig.maxTokens && finalConfig.maxTokens > 0) {
      llmConfig.maxTokens = finalConfig.maxTokens;
    }

    const llm = new ChatOpenAI(llmConfig);

    const agent = await createReactAgent({
      llm,
      tools,
      prompt,
    });

    const agentExecutor = new AgentExecutor({
      agent,
      tools,
      returnIntermediateSteps: true,
    });

    const result = await agentExecutor.invoke(
      {
        input: `你是一个地理专题图制作专家，专注于风场、洋流和海温相关的专题图生成。

【可用数据源】
- 风场数据
- 洋流数据
- 海温数据

【可用专题图类型】
- 风场图
- 洋流图
- 海温分布图

【颜色方案】
blue、red、green、purple、rainbow

【显示选项】
grid（经纬网）、scale（比例尺）、legend（图例）、labels（标签）

请根据用户需求选择合适的配置并生成专题图。
请提供清晰且专业的响应。

当前任务：${input}
`,
        chat_history: thematicChatHistory
      },
      {
        callbacks: [{
          handleAgentAction(action) {
            onIntermediateStep(`正在处理: ${action.log}`);
          },
          handleChainEnd(outputs) {
            if (outputs.intermediateSteps?.length > 0) {
              const summary = outputs.intermediateSteps.map(step =>
                `操作: ${step.action.tool}, 结果: ${step.observation}`
              ).join('\\n');
              
              onIntermediateStep(`执行摘要:\\n${summary}`);
            }
          }
        }]
      }
    );

    return result.output;
  } catch (e) {
    console.error(e);
    return `发生错误: ${e.message}`;
  }
};

// 2. Create the agent
export const runAgent = async (input, onIntermediateStep, mapTools, config = {}) => {
  const agentContext = {
    plannedPath: null,
  };
  const tools = createGisTools(mapTools, agentContext);

  try {
    const prompt = await pull("hwchase17/react-chat");

    // 默认配置
    // const defaultConfig = {
    //   baseURL: 'https://api.siliconflow.cn',
    //   openAIApiKey: 'sk-kxvlqqwjbkgizqedqrcrgnaxpzuluyyjbbplygzomtsmmdmc',
    //   modelName: 'Pro/deepseek-ai/DeepSeek-V3',
    //   temperature: 0,
    //   maxTokens: null
    // };

    const defaultConfig = {
      baseURL: 'https://ai.nengyongai.cn/v1',
      openAIApiKey: 'sk-1UFn4uObTYmMq2J38sSnSgwQT6sQOmCcIVmkL8fUCR8X0BLA',
      modelName: 'gpt-4o-mini',
      temperature: 0,
      maxTokens: null
    };

    // const defaultConfig = {
    //   baseURL: 'https://api.o3.fan',
    //   openAIApiKey: 'sk-9YFxNCpKAvPgTfyt723c43689e7443D4B4Fc796eD366F604',
    //   modelName: 'gpt-4o-mini',
    //   temperature: 0,
    //   maxTokens: null
    // };

    // 合并配置，优先使用传入的配置
    const finalConfig = { ...defaultConfig, ...config };

    // 构建LLM配置对象
    const llmConfig = {
      modelName: finalConfig.modelName,
      temperature: finalConfig.temperature,
      openAIApiKey: finalConfig.openAIApiKey,
      configuration: {
        baseURL: finalConfig.baseURL,
      }
    };

    // 如果设置了maxTokens，则添加到配置中
    if (finalConfig.maxTokens && finalConfig.maxTokens > 0) {
      llmConfig.maxTokens = finalConfig.maxTokens;
    }

    const llm = new ChatOpenAI(llmConfig);

    // fcj - 注释掉的备用配置
    // const llm = new ChatOpenAI({
    //   modelName: "deepseek-chat",
    //   temperature: 0,
    //   openAIApiKey: 'sk-29f1d408a9a8433a8614420b25ce2c88',
    //   configuration: {
    //     baseURL: "https://api.deepseek.com", 
    //   }
    // });

    const agent = await createReactAgent({
      llm,
      tools,
      prompt,
    });

    const agentExecutor = new AgentExecutor({
      agent,
      tools,
      returnIntermediateSteps: true, // 是否返回中间步骤
    });

    const result = await agentExecutor.invoke(
      {
        input: `
              你是一个地理信息系统(GIS)专家。
              你的目标是通过调用可用工具在地图上绘制来帮助用户。
              
              重要提示：
              1. 当需要查询多个港口并规划路径时，优先使用searchPortsAndPlanPath工具，它可以并行查询多个港口，大大提高效率。
              2. 例如：用户说"绘制青岛港到烟台港的最短路径"，应该使用searchPortsAndPlanPath工具，输入{"ports": ["青岛港", "烟台港"]}。
              3. 只有在需要单独查询单个港口信息时才使用searchPort工具。
              4. 分析用户的请求并将其分解为最少的工具调用，优先选择能够并行处理的工具。
              
              提供清晰且信息丰富的响应。
              响应速度越快越好！
              当前任务: ${input}
            `,
        chat_history: chatHistory
      },
      {
        callbacks: [{
          handleAgentAction(action) {
            onIntermediateStep(`思考中: ${action.log}`);
          },
          handleChainEnd(outputs) {
            if (outputs.intermediateSteps?.length > 0) {
              const summary = outputs.intermediateSteps.map(step =>
                `操作: ${step.action.tool}, 输入: ${step.action.toolInput}, 结果: ${step.observation}`
              ).join('\\n');
              
              onIntermediateStep(`执行摘要:\\n${summary}`);
            }
          }
        }]
      }
    );

    return result.output;
  } catch (e) {
    console.error(e);
    return `发生错误: ${e.message}`;
  }
}; 